namespace UMC.Host;

using System;
using System.IO;
using System.Net;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using UMC.Net;

public class HttpsMimeSocket : HttpMime
{

    public override string Scheme => "https";

    public HttpsMimeSocket(System.IO.Stream stream, String host, String ip)
    {
        this._stream = stream;
        this.ActiveTime = UMC.Data.Utility.TimeSpan();

        this.pid = stream.GetHashCode();

        this._Host = host;

        this._remoteIpAddress = ip;

        HttpMimeServier.httpMimes.TryAdd(pid, this);
        Read(new HttpMimeRequest(this));

    }
    Stream _stream;
    int pid = 0;
    // public int Id => pid;
    public override int Id => pid;
    String _remoteIpAddress, _Host;
    public override String Host => _Host;
    public override String RemoteIpAddress => _remoteIpAddress;

    public override void Write(byte[] buffer, int offset, int count)
    {
        if (isDispose == false)
        {
            try
            {

                _stream.Write(buffer, offset, count);
            }
            catch
            {
                this.Dispose();
            }
        }
    }



    public override void OutputFinish()
    {
        try
        {
            Read(new HttpMimeRequest(this));

            this.ActiveTime = UMC.Data.Utility.TimeSpan();
            this.TimeOut = 20;
        }
        catch
        {
            this.Dispose();
        }
    }
    public override void PrepareRespone(HttpMimeRequest httpMimeRequest)
    {
        this.TimeOut = 300;
        base.PrepareRespone(httpMimeRequest);
    }
    public override void Subscribe(HttpMimeRequest webRequest)
    {
        OutText(401, "只支持Http形式订阅");
    }
    protected override void WebSocket(NetContext context)
    {
        if (context.Tag is HttpWebRequest)
        {
            var webr = context.Tag as HttpWebRequest;
            this.WebSocket(webr);
        }
    }
    bool isDispose = false;
    public override void Dispose()
    {
        if (this._data != null)
        {
            System.Buffers.ArrayPool<byte>.Shared.Return(this._data);
        }
        if (isDispose == false)
        {
            isDispose = true;
            try
            {
                _stream.Close();
                _stream.Dispose();
                _data = null;
                _webSocket?.Dispose();
            }
            catch
            {

            }
        }
        HttpMimeServier.httpMimes.TryRemove(pid, out var _);

    }
    async void WebSocket(HttpWebRequest webRequest)
    {
        try
        {
            var url = webRequest.RequestUri;


            webRequest.Headers["Connection"] = "Upgrade";


            var client = new Socket(SocketType.Stream, ProtocolType.Tcp);

            await client.ConnectAsync(url.Host, url.Port);


            if (url.Scheme == "https")
            {
                SslStream ssl = new SslStream(new NetworkStream(client, true), false, (sender, certificate, chain, sslPolicyErrors) => true);
                await ssl.AuthenticateAsClientAsync(url.Host, null, SslProtocols.None, false);
                var ws = new HttpsWebSocket(this, ssl);
                await ssl.WriteAsync(ws.buffer, 0, UMC.Net.NetHttpResponse.Header(webRequest, ws.buffer));

                _webSocket = ws;// new HttpsMimeSocketWebSocket(this, ssl);
            }
            else
            {
                var ws = new HttpWebSocket(this, client);
                client.Send(ws.buffer, 0, UMC.Net.NetHttpResponse.Header(webRequest, ws.buffer), SocketFlags.None);
                _webSocket = ws;// new HttpWebSocket(this, client);

            }

            HttpMimeServier.httpMimes.TryRemove(this.pid, out var _);

        }
        catch (Exception ex)
        {
            OutText(500, ex.ToString());
        }
    }

   
    WebSocket _webSocket;
    byte[] _data = System.Buffers.ArrayPool<byte>.Shared.Rent(0x600);// new byte[0x600];

    

    async void Read(HttpMimeRequest req)
    {
        int size = 0;
        try
        {
            size = await _stream.ReadAsync(this._data, 0, this._data.Length);
        }
        catch
        {
            this.Dispose();
            return;
        }
        if (size > 0)
        {
            this.ActiveTime = UMC.Data.Utility.TimeSpan();
            try
            {
                req.Receive(this._data, 0, size);
            }
            catch (Exception ex)
            {
                this.OutText(500, ex.ToString());

                return;
            }
        }
        else
        {
            this.Dispose();
            return;
        }

        if (req.IsHttpFormatError)
        {
            req.Dispose();
            this.Dispose();
            return;
        }

        if (req.IsWebSocket == false && req.IsMimeFinish == false)
        {
            Read(req);
        }

    }

}
